/*

cimahis - Software para el analisis de imagenes de corte histologico

Copyright (C) Andrés De Abreu 2010 <jadabreu @ gmail . com>


Este programa es software libre. Puede redistribuirlo y/o modificarlo bajo los términos
de la Licencia Pública General de GNU según es publicada por la Free Software Foundation,
bien de la versión 2 de dicha Licencia o bien (según su elección) de cualquier versión
posterior.

Este programa se distribuye con la esperanza de que sea útil, pero SIN NINGUNA GARANTÍA,
incluso sin la garantía MERCANTIL implícita o sin garantizar la CONVENIENCIA PARA UN
PROPÓSITO PARTICULAR. Véase la Licencia Pública General de GNU para más detalles.

Debería haber recibido una copia de la Licencia Pública General junto con este programa.
Si no ha sido así, escriba a la Free Software Foundation, Inc.,
en 675 Mass Ave, Cambridge, MA 02139, EEUU.

    //ACERCA DE filtros.cpp
    *
    * Implementación de la clase filtro y de las subclases filtroMediana, filtroBilateral
    * y filtroGauss.
    *

*/


#include "color/filtros.h"
#include "fstream"
#include <iostream>
#include "string.h"

using namespace std;

filtros::filtros(string nombreFiltro) //Constructor general de la clase.. se le debe pasar el nombre del filtro como parametro
{
    ifstream in("color/datosFiltros.in"); //leemos el archivo
    string aux;
    int aux1,aux2,aux3;
    vector<int> cola;
    bool bandera=false;
    int temp;
    vector<int>::iterator it;
    vector<int>::iterator it2;



    if(!in) {
        cout << " No es posible abrir fichero datosFiltro.in\n ";
    }

    while((in.eof()==false)||(bandera=false))  //mientras el archivo tenga datos y no se haya encontrado en filtro continuar
    {
        in >> aux >> aux1 >> aux2>> aux3; //leer primeros cuatro parametros


        int n=aux3; //aux3 tiene el numero de parametros extra del filtro

        for(int i=0;i<n;i++) //si existen parametros extra los recorremos
        {
            in >> temp;
            cola.push_back(temp); //almacenamos los parametros extra en una cola

        }
        if(aux==nombreFiltro) //si el filtro leido es el que queremos contruir.. entramos en el if
        {
            nombre.assign(aux);
            dimensiones[0]=aux1; //asignamos el nombre y paramtros del filtro
            dimensiones[1]=aux2;
            nParametrosExtra=aux3;

            it = parametroExtra.begin();  //guardamos los parametros extra en una lista
            it2=cola.end();
            parametroExtra.insert(it,it2-nParametrosExtra,it2);

            bandera=true; //indicamos que ya conseguimos el filtro deseado

        }
    }
    in.close(); //cerrar archivo
}

void filtros::fijarTamanoKernel(int a,int b) //fijar las dimensiones del kernel
									   //(por ejemplo fijarKernel(3,3) para aplicar kernel 3x3)
{
    dimensiones[0]=a;
    dimensiones[1]=b;
}

vector <int> filtros::obtenerTamanoKernel() //retorna un vector con las 2 dimensiones del kernel
{
    vector<int> kernel;
    kernel.push_back(dimensiones[0]);
    kernel.push_back(dimensiones[1]);
    return kernel;
}
void filtros::fijarParametroExtra(int n,int a)
//fijar un parametro extra
//n es la posicion en el vector de parametros donde se va a guardar
//a es el valor del parametro
												
{
    if(n<nParametrosExtra)
    {
        parametroExtra.at(n)=a;
    }

}

int  filtros::obtenerParametroExtra(int n)
{
// retorna el parametro extra guardado en la posicion n del vector de parametros

    if(n<nParametrosExtra)
    {
        return parametroExtra.at(n);
    }
    else
        return 0;
}

string filtros::obtenerNombre()
{
// retorna el nombre del filtro
    return nombre;
}

vector <int> filtros::obtenerParametrosExtra()
{
//retorna el vector que contiene todos los parametros extra
    return parametroExtra;
}

int filtros::obtenerNParametrosExtra()
{
//este metodo retorna el numero de parametros extra que posee el filtro
    return nParametrosExtra;
}

/////////////////////////////Filtro Mediana///////////////////////////////////

filtroMediana::filtroMediana() : filtros("Mediana")
{
   //el constructor esta vacio ya que se usa el contructor padre con el parametro Mediana
}

void filtroMediana::filtrar(IplImage  *img)
{
	//funcion de  OpenCV que aplica un filtro de mediana 
	//se usa de esta manera:
	//cvSmooth(imagen fuente,imagen destino, tipo de filtro, a,b)
	//a y b son las dimensiones del kernel
    cvSmooth(img,img,CV_MEDIAN,dimensiones[0],dimensiones[1]);
}

/////////////////////////////////Filtro gaussiano////////////////////////////////////////////////

filtroGauss::filtroGauss() : filtros("Gauss")
{
   //el constructor esta vacio ya que se usa el contructor padre con el parametro Gauss
}

void filtroGauss::filtrar(IplImage  *img)
{
	//funcion de  OpenCV que aplica un filtro gaussiano 
	//se usa de esta manera:
	//cvSmooth(imagen fuente,imagen destino, tipo de filtro, a,b)
	//a y b son las dimensiones del kernel
    cvSmooth(img,img,CV_GAUSSIAN,dimensiones[0],dimensiones[1]);
}

///////////////////////////////////Filtro MEan shift//////////////////////////////////
filtroMeanShift::filtroMeanShift() : filtros("MeanShift")
{
    //el constructor esta vacio ya que se usa el contructor padre con el parametro MeanShift
}

void filtroMeanShift::filtrar(IplImage  *img)
{
    img=img;
    //este metodo de OpenCV es batante inestable, aun no esta listo para usarse, solo para pruebas
    //cvPyrMeanShiftFiltering(img,img,parametroExtra[0],parametroExtra[1],1 );
}

/////////////////////////////////////////FIltro Bilateral/////////////////////////

filtroBilateral::filtroBilateral() : filtros("Bilateral")
{
    //el constructor esta vacio ya que se usa el contructor padre con el parametro Bilateral
}


void filtroBilateral::filtrar(IplImage  *img)
{
	//funcion de  OpenCV que aplica un filtro Bilateral
	//se usa de esta manera:
	//cvSmooth(imagen fuente,imagen destino, tipo de filtro, a,b,c,d)
	//a y b son las dimensiones del kernel (deben ser 0 sino da error)
	//c indica el dominio espacial
	//d indica el rango de colores que se va a tomar
    IplImage* img2 = cvCreateImage( cvGetSize(img), IPL_DEPTH_8U, 3 );
    img2 = cvCloneImage(img);
    cvSmooth(img2,img,CV_BILATERAL,dimensiones[0],dimensiones[1],parametroExtra[0],parametroExtra[1]);
    cvReleaseImage(&img2);
}

